#include "utils.h"

#include <boost/tokenizer.hpp>
#include <boost/regex.hpp>

// 用于匹配名称的正则表达式模版，其中第一个参数为level, 其二个参数是软件名称
static const char *g_badpackages[] = {
    "centos","debian","ubuntu","redhat","addon","agent","apps","base","bin","bsd","cache","check","client","command",
    "common","configuration","control","core","cron","data","database","dev","editor","events","extras","family","file",
    "files","form","ftp","generic","gnu","headers","http","info","installation","kernel","legacy","linux","load","manager",
    "message","module","monitor","net","network","one","open","patch","path","plugin","plugins","release","router","secure",
    "security","server","ssl","software","standard","support","system","team","text","the","theme","time","toolkit","tools",
    "unix","update","user","utility","viewer","web","wifi","windows","wireless"
};
static const char *g_valid_platforms[] = {"linux","linux_crisv32","linux_mips","linux_ppc","linux_sparc","lin_x86","lin_x86-64","multiple"};

std::string software::utils::purge_version_string(const char *version_c)
{
    std::string version = version_c;
    boost::regex seps("[^0-9.]");
    boost::sregex_token_iterator iter(version.begin(), version.end(), seps, {-1, 0});
    version = *iter;
    if (!version.empty() && version[version.length()-1] == '.')
    {
        version = version.substr(0, version.length()-1);
    }
    return version;
}

std::list<std::string> software::utils::extract_versions(const char *title_string)
{
    std::list<std::string> rc;
    std::string version(title_string);
    boost::regex seps("\\s-|\\(\\)|\\&");
    boost::sregex_token_iterator iter(version.begin(), version.end(), seps, {-1 , 0});
    version = *iter;

    boost::char_separator<char> sep_space(" ");
    typedef boost::tokenizer< boost::char_separator<char> > Tokens;
    Tokens tokens(version, sep_space);

    for (Tokens::iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
    {
        std::string possible_version = *iter;
        std::string::size_type pos = std::string::npos;
        if (isdigit(possible_version[0]))
        {
            if (possible_version.find("/") != std::string::npos)
            {
                boost::char_separator<char> sep_oblique("/");
                Tokens tokens_by_oblique(possible_version, sep_oblique);
                for (Tokens::iterator iter_by_oblique = tokens_by_oblique.begin(); iter_by_oblique != tokens_by_oblique.end(); ++iter_by_oblique)
                {
                    std::string multiversion = *iter_by_oblique;
                    if ((pos = multiversion.find("-")) != std::string::npos)
                    {
                        multiversion = multiversion.substr(0, pos);
                    }
                    multiversion = purge_version_string(multiversion.c_str());
                    if (!multiversion.empty())
                    {
                        rc.push_back(multiversion);
                    }
                }
            }
            else if ((pos = possible_version.find("-")) != std::string::npos)
            {
                rc.push_back(purge_version_string(possible_version.substr(0, pos).c_str()));
            }
            else
            {
                rc.push_back(purge_version_string(possible_version.c_str()));
            }
        }
    }

    return rc;
}

std::string software::utils::clean_name(const char *software_name)
{
    const size_t g_badpackages_length = sizeof(g_badpackages) / sizeof(const char*);
    std::string sn(software_name);

    for (size_t var = 0; var < g_badpackages_length; ++var)
    {
        boost::regex reg(g_badpackages[var], boost::regex::icase);
        sn = boost::regex_replace(sn, reg, "");
    }

    return sn;
}

std::string software::utils::soft_name(const char *sn)
{
    std::string rc = sn;
    // re2::RE2::Replace(&rc, "\\+", "\\\\+");
    boost::regex reg("\\+");
    rc = boost::regex_replace(rc, reg, "\\\\+");
    return rc;
}

bool software::utils::is_valid_platforms(const char *platform)
{
    bool is_valid = false;

    if (NULL == platform)
    {
        return is_valid;
    }

    size_t g_valid_platforms_count = sizeof(g_valid_platforms) / sizeof(g_valid_platforms[0]);
    for (size_t var = 0; var < g_valid_platforms_count; ++var)
    {
        if (0 == strcmp(platform, g_valid_platforms[var]))
        {
            is_valid = true;
            break;
        }
    }

    return is_valid;
}
